package com.jinxin.platform.cdacsrecord.core.service;

import com.alibaba.fastjson.JSONObject;
import com.jinxin.platform.cdacsrecord.core.mapper.*;
import com.jinxin.platform.cdacsrecord.core.pojo.domains.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import static com.jinxin.platform.cdacsrecord.core.utils.URLEncoder.encodeURIComponent;

/**
 * Description: apcos-acs
 * Created by 34759 on 2020/4/24 9:47
 */
@Service
@Transactional
@Slf4j
public class AcsControlAsyncService {

    @Resource
    private JurenAcsControlUserMethodMapper userMethodMapper;
    @Resource
    private JurenAcsControlVisitorMethodMapper visitorMethodMapper;
    @Autowired
    private AcsControlDeviceInfoService deviceInfoService;
    @Resource
    private JurenAcsControlDeviceSubscribeMapper deviceSubscribeMapper;
    @Resource
    private JurenAcsControlUserInfoMapper userInfoMapper;
    @Resource
    private JurenAcsControlRecordInfoMapper recordInfoDao;

    private static String regOperation = "Register face information";
    private static String delOperation = "Delete face information";

    /**
     * 异步批量添加用户默认的支持模式
     * @param infoDOList
     */
    @Async
    public void upUserMethodInfo(List<AcsControlUserInfoDO> infoDOList){
        AcsControlVisitorMethodDO selMethodDO = new AcsControlVisitorMethodDO();
        List<AcsControlVisitorMethodDO> methodDOList = visitorMethodMapper.selDOByInfo(selMethodDO );
        AcsControlUserMethodDO userMethodDO = new AcsControlUserMethodDO();
        for(AcsControlUserInfoDO userInfoDO: infoDOList ){
            for(AcsControlVisitorMethodDO methodDO1: methodDOList  ){
                userMethodDO.setUserId(userInfoDO.getUserId());
                userMethodDO.setVisitorMethodKey(methodDO1.getVisitorMethodKey());
                userMethodDO.setCreateTime(LocalDateTime.now());
                userMethodMapper.insert(userMethodDO);
                log.info("保存用户方式："+userMethodDO.toString());
            }
        }
    }

    /**
     * 异步通知设备某用户的新照片  先删除再注册
     * @param infoDOList
     * @param newBase64
     */
    @Async
    public void upUserFace2Device(List<AcsControlUserInfoDO> infoDOList, String newBase64  ){
        for (AcsControlUserInfoDO acsControlUserInfoDO :  infoDOList) {
            if(regUserFace(acsControlUserInfoDO,acsControlUserInfoDO.getUserName(),newBase64 )){
                log.info("更新用户人脸信息成功--" + acsControlUserInfoDO.getUserName());
            }else{
                log.info("更新用户人脸信息失败--" + acsControlUserInfoDO.getUserName());
            }
        }
    }

    /**
     * 注册访客人脸信息
     * @param uid
     * @param vface
     * @param vname 下发给设备是 访客+name
     */
    @Async
    public void regVisitorFace2Device(String uid,String vface,String vname ){
        AcsControlUserInfoDO userInfoDO = userInfoMapper.selById(uid);
        if( null == userInfoDO ){
            log.error("未找到操作者信息--"+uid);
        }
        if(regUserFace(userInfoDO,"访客"+vname,vface )){
            log.info("注册访客人脸信息成功--"+ "访客"+vname);
        }else{
            log.info("注册访客人脸信息失败--"+ "访客"+vname);
        }
    }

    /**
     * 注册人脸信息 先删除同ID信息再上传
     * @param userInfoDO
     * @param uName 姓名单独传递，可区分 业主和访客
     * @param newBase64
     * @return
     */
    public boolean regUserFace(AcsControlUserInfoDO userInfoDO,String uName, String newBase64 ){
        boolean res = true;
        try {
            JSONObject jsonObject = new JSONObject();
            String mac;
            //查询UID对应的设备ID
            AcsControlDeviceInfo deviceInfoParam = new AcsControlDeviceInfo();
            deviceInfoParam.setBuildingLoc(userInfoDO.getUserBlockName());
//            deviceInfoParam.setRoomLoc(userInfoDO.getUserRoomName());
            deviceInfoParam.setUserInfo(userInfoDO.getUserId());
            List<AcsControlDeviceInfo> deviceInfoList = deviceInfoService.selAllByParam(deviceInfoParam);
            for (AcsControlDeviceInfo deviceInfo:deviceInfoList ){
                mac = deviceInfo.getDeviceId();
                jsonObject.put("p1", userInfoDO.getUserBlockName()+"-"+userInfoDO.getUserRoomName()+"-"+uName);
                String controlParams = encodeURIComponent(jsonObject.toJSONString());
                deviceInfoService.controlDevice(deviceSubscribeMapper.queryById(mac), controlParams, delOperation);
                jsonObject = new JSONObject();
                jsonObject.put("p1", userInfoDO.getUserBlockName()+"-"+userInfoDO.getUserRoomName()+"-"+uName);
                jsonObject.put("p2", newBase64);
                controlParams = jsonObject.toJSONString();
                if( !deviceInfoService.controlDevice(deviceSubscribeMapper.queryById(mac), URLEncoder.encode(controlParams, "UTF-8"), regOperation) ){
                    log.info("下发人脸信息失败--"+ controlParams );
                    res = false;
                }
            }
        } catch (UnsupportedEncodingException e) {
            log.error(uName+"注册人脸失败",e);
            res = false;
        }
        return res;
    }

    /**
     * 删除访客人脸信息
     * @param recordInfoList
     */
    @Async
    public void delFace2Device( List<AcsControlRecordInfo> recordInfoList ){
        AcsControlUserInfoDO userInfoDO ;
        for(AcsControlRecordInfo recordInfo: recordInfoList ){
            // 查询访客操作者
            JSONObject jsonObject = new JSONObject();
            String mac;
            userInfoDO = userInfoMapper.selById(recordInfo.getOperatorId());
            //查询UID对应的设备ID
            AcsControlDeviceInfo deviceInfoParam = new AcsControlDeviceInfo();
            deviceInfoParam.setBuildingLoc(userInfoDO.getUserBlockName());
//            deviceInfoParam.setRoomLoc(userInfoDO.getUserRoomName());
            deviceInfoParam.setUserInfo(userInfoDO.getUserId());
            List<AcsControlDeviceInfo> deviceInfoList = deviceInfoService.selAllByParam(deviceInfoParam);
            for (AcsControlDeviceInfo deviceInfo:deviceInfoList ){
                mac = deviceInfo.getDeviceId();
                jsonObject.put("p1", userInfoDO.getUserBlockName()+"-"+userInfoDO.getUserRoomName()+"-访客"+recordInfo.getVisitorName());
                String controlParams = encodeURIComponent(jsonObject.toJSONString());
                if(deviceInfoService.controlDevice(deviceSubscribeMapper.queryById(mac), controlParams, delOperation) ){
                    // 删除成功，更新访客状态
                    recordInfo.setState(recordInfo.getState()+"1" );
                    recordInfoDao.update(recordInfo);
                }
            }
        }
    }

    /**
     * 根据MAC查询开门设备信息 并添加开门记录
     * @param mac
     */
    @Async
    public void addReportOpenLog(String mac,String openType,String name ){
        AcsControlDeviceInfo deviceInfo = deviceInfoService.selectByDeviceId(mac);
        if(deviceInfo != null ){
            AcsControlRecordInfo recordInfo = new AcsControlRecordInfo();
            recordInfo.setRecordType("1");
            recordInfo.setDeviceId(deviceInfo.getDeviceId());
            recordInfo.setDeviceName(deviceInfo.getDeviceName());
            recordInfo.setDeviceMainBody(deviceInfo.getBuildingLoc());
            recordInfo.setCreateTime(LocalDateTime.now());
            recordInfo.setRecordInfo(openType);//开门方式
            recordInfo.setMainBodyIdentity(name);//人名
            recordInfoDao.insertSelective(recordInfo);
            log.info("新增开门记录："+ recordInfo.toString());
        }else{
            log.info("未录入门禁系统的设备："+ mac);
        }
    }

    /**
     * 通话记录-- 发起呼叫
     * @param event
     * @param uid
     */
    @Async
    public void addCallLog(String event,String uid,String roomId,String listenedUser  ){
        // 呼叫  {"data":{"audioOnly":false,"inviteID":"8","room":"3cd570e2-7f89-4b4b-b4cf-c127196937971589438606820","userList":"7777"},"eventName":"__invite"}
        if(StringUtils.isEmpty(event)||StringUtils.isEmpty(uid)||StringUtils.isEmpty(roomId)||StringUtils.isEmpty(listenedUser) ){
            log.error("入参不完整 ");
            return;
        }
        AcsControlRecordInfo recordInfo = new AcsControlRecordInfo();
        recordInfo.setRecordType("2");
        recordInfo.setRecordInfo(roomId);
        recordInfo.setCreateTime(LocalDateTime.now());

        AcsControlDeviceInfo deviceInfoSel = new AcsControlDeviceInfo();
        deviceInfoSel.setCallNumber(uid);
        List<AcsControlDeviceInfo> deviceInfoList = deviceInfoService.selAllByParam(deviceInfoSel);
        if(deviceInfoList == null || deviceInfoList.size()==0 ){
            log.error("未查询到呼叫设备信息 ");
            return;
        }
        recordInfo.setDeviceId(deviceInfoList.get(0).getDeviceId());
        recordInfo.setDeviceName(deviceInfoList.get(0).getDeviceName());
        deviceInfoSel.setCallNumber(listenedUser);
        deviceInfoList = deviceInfoService.selAllByParam(deviceInfoSel);
        if(deviceInfoList == null || deviceInfoList.size()==0 ){
            log.error("未查询到接听设备信息 ");
            return;
        }
        recordInfo.setDeviceMainBodyId(deviceInfoList.get(0).getDeviceId());
        recordInfo.setDeviceMainBody(deviceInfoList.get(0).getDeviceName());
        recordInfo.setState("1");
        recordInfoDao.insertSelective(recordInfo);
        log.info("新增呼叫记录--"+recordInfo.toString());
    }

    /**
     * 接听 离开时候更新通话记录
     * @param room
     * @param uid
     * @param eventName
     */
    @Async
    public void  upCallLog(String room,String uid ,String eventName){
        // --接通 {"data":{"room":"3cf59a9c-22e6-4411-9214-36174988ec0f1589438642688","userID":"8109"},"eventName":"__join"}
        // --挂断 {"data":{"fromID":"8109","room":"3cf59a9c-22e6-4411-9214-36174988ec0f1589438642688"},"eventName":"__leave"}
        if(StringUtils.isEmpty(room)||StringUtils.isEmpty(uid) ){
            log.error("入参不完整 ");
            return;
        }
        AcsControlDeviceInfo deviceInfoSel = new AcsControlDeviceInfo();
        deviceInfoSel.setCallNumber(uid);
        List<AcsControlDeviceInfo> deviceInfoList = deviceInfoService.selAllByParam(deviceInfoSel);
        if(deviceInfoList == null || deviceInfoList.size()==0 ){
            log.error("未查询到接听设备信息 ");
            return;
        }
        AcsControlRecordInfo recordInfo = recordInfoDao.queryByInfo(room);
        if(recordInfo == null){
            log.error("未查询到通话记录信息");
            return;
        }
        if(eventName.equals("__join") ){
            if(!recordInfo.getDeviceMainBodyId().equals(deviceInfoList.get(0).getDeviceId()) ){
                log.error(" 查询到通话记录信息接听方错误");
                return;
            }
            if(!recordInfo.getState() .equals("1") ){
                log.error("查询到通话记录状态错误--"+recordInfo.getState());
                return;
            }
            recordInfo.setState("2");
            recordInfo.setListenedTime(LocalDateTime.now());
        }else if(eventName.equals("__leave") ){
            //不判断离开房间的用户信息
            recordInfo.setState("3");
            //计算通话时长 min
            long minutes = 0;
            if(null != recordInfo.getListenedTime() ){
                Duration duration = Duration.between(recordInfo.getListenedTime(),LocalDateTime.now());
                minutes = duration.toMinutes();//相差的分钟数
            }
            recordInfo.setTaikDuration(String.valueOf(minutes) );
        }
        recordInfoDao.update(recordInfo);
        log.info("更新通话记录--"+recordInfo.toString());
    }


}
